#include "ringbuffer.h"


// 创建通用环形缓冲区
generic_ring_buffer_t *generic_ring_buffer_create(rt_size_t size, rt_size_t element_size) {
    generic_ring_buffer_t *buffer;
    uint8_t *data_pool;

    RT_ASSERT(size > 0 && element_size > 0);

    size = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);

    buffer = (generic_ring_buffer_t *)rt_malloc(sizeof(generic_ring_buffer_t));
    if (buffer == RT_NULL) {
        return RT_NULL;
    }

    data_pool = (uint8_t *)rt_malloc(size * element_size);
    if (data_pool == RT_NULL) {
        rt_free(buffer);
        return RT_NULL;
    }

    buffer->lock = rt_mutex_create("buf_lock", RT_IPC_FLAG_PRIO);
    rt_atomic_store(&buffer->write_idx, 0);
    buffer->read_idx = 0;
    buffer->data = data_pool;
    buffer->size = size;
    buffer->element_size = element_size;

    return buffer;
}

// 向缓冲区写入数据
rt_bool_t generic_ring_buffer_put(generic_ring_buffer_t *buffer, const void *element) {
    if (buffer == RT_NULL || element == RT_NULL) {
        return RT_FALSE;
    }

    rt_size_t current_write = rt_hw_atomic_load(&buffer->write_idx);
    rt_size_t next_write = (current_write + 1) % buffer->size;

    // 检查缓冲区是否满
    if (buffer->read_idx == next_write) {
        return RT_FALSE; // 缓冲区满
    }

    // 写入数据
    rt_memcpy(buffer->data + current_write * buffer->element_size, element, buffer->element_size);
    rt_atomic_store(&buffer->write_idx, next_write); // 原子更新写指针
    return RT_TRUE;
}

// 从缓冲区读取数据
rt_bool_t generic_ring_buffer_get(generic_ring_buffer_t *buffer, void *element) {
    if (buffer == RT_NULL || element == RT_NULL) {
        return RT_FALSE;
    }

    rt_err_t err;
    rt_size_t current_read, current_write;

    // 申请互斥锁
    err = rt_mutex_take(buffer->lock, RT_WAITING_FOREVER);
    if (err != RT_EOK) return RT_FALSE;

    current_read = buffer->read_idx;
    current_write = rt_hw_atomic_load(&buffer->write_idx);

    if (current_read == current_write) {
        rt_mutex_release(buffer->lock); // 无数据，释放锁
        return RT_FALSE;
    }

    // 读取数据前记录当前读指针
    rt_size_t read_pos = current_read;
    buffer->read_idx = (current_read + 1) % buffer->size; // 更新读指针

    rt_mutex_release(buffer->lock); // 释放锁

    // 数据拷贝
    rt_memcpy(element, buffer->data + read_pos * buffer->element_size, buffer->element_size);
    return RT_TRUE;
}

// 销毁通用环形缓冲区
void generic_ring_buffer_destroy(generic_ring_buffer_t *buffer) {
    if (buffer == RT_NULL) {
        return;
    }

    rt_mutex_detach(buffer->lock);
    rt_free(buffer->data);
    rt_free(buffer);
}